package com.neo.design.chain.approve;

import com.neo.design.chain.ChainContext;
import com.neo.design.chain.ChainRequest;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.LinkedList;
import java.util.List;

/**
 * 审批流程业务链中心<p/>
 * <p>
 * 当定义完成业务链后，由该类进行业务链的初始化和组装<p/>
 * 这里只是示例代码，但模板代码基本通用，参照:{@link com.neo.design.chain.payment.PaymentContext}，
 * 比较而言，业务链中心的初始化和组装逻辑基本一致
 * <p/>
 * 需要注意的是：如果在项目中需要使用到多个业务链，可以使用注解{@link Order}来定义业务链的顺序，调用频繁或者业务比较重要的可以进行优先加载。
 *
 * @author kevin
 * @see com.neo.design.chain.ChainContext
 */
@Order(1)
@Component
@Slf4j
public class ApproveContext implements ChainContext<ApproveRequest, ApproveResult> {

    /**
     * 业务链节点处理器集合
     */
    @Resource
    private List<ApproveHandler> handlers;

    /**
     * 业务链处理节点入口，可以使用@Order注解来定义业务链的顺序，数字越小，优先执行
     */
    private ApproveHandler handler;

    /**
     * 审批链初始化，这里需要注意的是，不要形成环链了。
     *
     * @see com.neo.design.chain.ChainContext#init()
     */
    @Override
    @PostConstruct
    public void init() {
        LinkedList<ApproveHandler> contexts = new LinkedList<>();
        handlers.forEach(hd -> {
            if (!contexts.isEmpty()) {
                contexts.getLast().setNext(hd);
            }
            contexts.add(hd);
            // 可以查看顺序链是否正确
            log.info("初始化审批业务链：{}", hd.getClass().getSimpleName());
        });
        handler = contexts.getFirst();
    }

    /**
     * 处理审批业务
     *
     * @param request 审批业务请求参数
     * @return 审批业务处理结果
     * @see com.neo.design.chain.ChainContext#handleRequest(ChainRequest)
     */
    @Override
    public ApproveResult handleRequest(ApproveRequest request) {
        Assert.notNull(handler, "容器初始化失败");
        return handler.handleRequest(request);
    }

    /**
     * 判断是否是审批业务
     *
     * @param request 业务请求参数 {@link ChainRequest}
     * @return true：是审批业务，false：不是审批业务
     * @see com.neo.design.chain.ChainContext#match(ChainRequest)
     */
    @Override
    public boolean match(ChainRequest request) {
        return request instanceof ApproveRequest;
    }
}
